/*************************************************************
 * @file		usb_desc.c
 * @brief		USB descriptors ,discribed USB spec1.1 chapter 9
 * @author		Jiang Kaigan
 * @version		V1.0
 * @date		2020-12-03
 * @par
 * @attention
 *
 * @history		2020-12-03 jkg	create this file
 */

/*file type declaration section*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*internal symbols import section*/
#include "usbclass.h"
#include "usb.h"
#include "usbdef.h"
#include "../driver_usb.h"

#pragma pack(1)
typedef struct
{
	int ind;
	CBufferBaseDesc desc;
} _t_index_descriptor;
#pragma pack()

#if 1
const UI8 tHidMSEReportDesc[] = {
	HidUsagePage(HID_USAGEPAGE_Generic),
	HidUsage(HID_USAGE_Mouse),
	HidCollectionApp(),
	HidUsage(HID_USAGE_Pointer),
	HidCollectionPhy(),
	HidUsagePage(HID_USAGEPAGE_Buttons),
	HidUsageMin8(1),
	HidUsageMax8(16),
	HidLogiMin8(0),
	HidLogiMax8(1),
	HidReportBits(1),
	HidReportCount(16),
	HidInput(0, 1, 0),

	HidUsagePage(HID_USAGEPAGE_Generic),
	HidUsage(HID_USAGE_AxisX),
	HidUsage(HID_USAGE_AxisY),
	HidUsage(HID_USAGE_AxisZ),
	HidLogiMin16(-32768),
	HidLogiMax16(32767),
	HidReportBits(16),
	HidReportCount(3),
	HidInput(0, 1, 1),

	HidEndCollection(),
	HidEndCollection(),
};
#endif
#if 0
const UI8 tHidMSEReportDesc[]={
	HidUsagePage(HID_USAGEPAGE_Generic),
	HidUsage(HID_USAGE_Mouse),
	HidCollectionApp(),
	HidUsage(HID_USAGE_Pointer),
	HidCollectionPhy(),
	HidReportID(REPORTID_REL_MOUSE),
	HidUsagePage(HID_USAGEPAGE_Buttons),
	HidUsageMin8(1),
	HidUsageMax8(8),
	HidLogiMin8(0),
	HidLogiMax8(1),
	HidReportBits(1),
	HidReportCount(8),
	HidInput(0, 1, 0),

	HidUsagePage(HID_USAGEPAGE_Generic),
	HidUsage(HID_USAGE_AxisX),
	HidUsage(HID_USAGE_AxisY),
	HidUsage(HID_USAGE_AxisZ),
	HidLogiMin16(-32768),
	HidLogiMax16(32767),
	HidReportBits(16),
	HidReportCount(3),
	HidInput(0, 1, 1),
	HidEndCollection(),
	HidEndCollection(),


	HidUsage(HID_USAGE_Mouse),
	HidCollectionApp(),
	HidUsage(HID_USAGE_Pointer),
	HidCollectionPhy(),
	HidReportID(REPORTID_ABS_MOUSE),
	HidUsagePage(HID_USAGEPAGE_Buttons),
	HidUsageMin8(1),
	HidUsageMax8(8),
	HidLogiMin8(0),
	HidLogiMax8(1),
	HidReportBits(1),
	HidReportCount(8),
	HidInput(0, 1, 0),

	HidUsagePage(HID_USAGEPAGE_Generic),
	HidUsage(HID_USAGE_AxisX),
	HidUsage(HID_USAGE_AxisY),
	HidUsage(HID_USAGE_AxisZ),
	HidLogiMin16(0),
	HidLogiMax16(32767),
	HidReportBits(16),
	HidReportCount(3),
	HidInput(0, 1, 0),
	HidEndCollection(),
	HidEndCollection(),
};
#endif

const UI8 tHidDbgReportDesc[] = {
	HidUsagePage(HID_USAGEPAGE_Customer),
	HidUsage(0x01),
	HidCollectionApp(),
	HidUsage(0x00),
	HidReportBits(8),
	HidReportCount(64),
	HidLogiMin8(0),
	HidLogiMax16(0xff),
	HidInput(0, 1, 0),
	HidUsage(0x00),
	HidReportBits(8),
	HidReportCount(64),
	HidLogiMin8(0),
	HidLogiMax16(0xff),
	HidOutput(0, 1, 0),
	HidEndCollection()};
const UI16 tUsbLanguageID[] = {
	0x04 + (USB_DESCTYPE_STRING << 8),
	_LANGUAGE_ID_};

const UI16 tUsbProductStr[] = {
	(((12 + 1) * 2)) + (USB_DESCTYPE_STRING << 8), 'M', 'o', 'b', 'v', 'o', 'i', '_', 'A', 'u', 'd', 'i', 'o'};
const UI16 tUsbVendorStr[] = {
	(((11 + 1) * 2)) + (USB_DESCTYPE_STRING << 8), 'M', 'o', 'b', 'v', 'o', 'i', 'C', 'o', 'r', 'p', '.'};
const UI16 tUsbSnStr[] = {
	(((10 + 1) * 2)) + (USB_DESCTYPE_STRING << 8), '1', '2', '3', '4', '3', '3', '3', '3', '3', '3'};

const CUsbDevDesc tUsbDeviceDescriptor = {
	sizeof(CUsbDevDesc),
	USB_DESCTYPE_DEVICE,
	USB_VERSION,
	USB_DEVICE_CLASS(0),
	USB_DEVICE_SUBCLASS(0),
	USB_DEVICE_PROTOCOL(0),
	USB_MAX_PACKET_LEN(64),
	_VID_,
	_PID_,
	0x0101,
	_Vendor_String_ID_,
	_Product_String_ID_,
	_Sn_String_ID_,
	USB_DEVICE_CONFIG_NUM(USB_MAX_CONFIG_NUM)};

#if 1
/*
 *MIC+SPK+Mouse+HID vendor IO
 */
// #define SZ_Audio_ACI(nIntfAs) 9 /*Interface AC*/ +
// 								  8 + ((nIntfAs)) + /*Header*/ +12 /*IT(1)*/ +
// 								  12 /*IT(2)*/ +
// 								  9 /*OT(1)*/ +
// 								  9 /*OT(2)*/ +
// 								  0 /*FU(1)*/ +
// 								  0 /*FU(2)*/ +
// 								  0

#define SZ_Audio_ACI(nIntfAs) 9 /*Interface AC*/ +                           \
								  8 + ((nIntfAs)) + /*Header*/               \
								  (nIntfAs) * (12 /*IT(2)*/ + 9 /*OT(1)*/) + \
								  0 /*FU(1)*/ +                              \
								  0 /*FU(2)*/ +                              \
								  0

#define SZ_Audio_ASI(nSR) 9 + /*Interface AS Bw0*/ +9 /*Interface AS Normal*/ + \
							  7 /*AS General*/ +                                \
							  8 + ((nSR)*3) /*AS FormatI*/ +                    \
							  9 /*Endpoint for Audio class*/ +                  \
							  7 /*Endpoint AS General*/ +                       \
							  0

#define SZ_HID_Intf(nEndp) 9 + /*HID Interface descriptor*/ +9 /*HID class descriptor*/ + \
							   7 * (nEndp) /*Endpoint descriptor*/ +                      \
							   0

#define SZ_CONFIG(nMicSR, nSpkSR, nIntfAs) 9 /*config*/ +                                \
											   SZ_Audio_ACI(nIntfAs) +                   \
											   SZ_Audio_ASI(nMicSR) /*MIC descs size*/ + \
											   SZ_Audio_ASI(nSpkSR) /*SPK descs size*/ + \
											   SZ_HID_Intf(1) /*HID Mouse descs size*/ + \
											   SZ_HID_Intf(2) /*HID DBG descs size*/ +   \
											   0

const UI8 tUsbConfig[] = {
	// USB_Gen_Config(SZ_CONFIG(1, 0, 1), USB_MAX_INTERFACE_NUM, 100),
	USB_Gen_Config(0x9d, USB_MAX_INTERFACE_NUM, 100),
	USB_AUDIO_InterfaceAC(USB_INTFID_AudioAC),
	USB_ACS_ACI_Header(SZ_Audio_ACI(1), 1), USB_INTFID_AudioAS_MIC, // USB_INTFID_AudioAS_SPK,
																	//	USB_ACS_ACI_IT(USBAUDIO_IT_SPK, 0, AUDIO_TERMTYPE_USB_STREAM, 2, AUDIO_CHANNEL_CONFIG(1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
	USB_ACS_ACI_IT(USBAUDIO_IT_MIC, 0, AUDIO_TERMTYPE_IT_MIC, 2, AUDIO_CHANNEL_CONFIG(1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
	USB_ACS_ACI_OT(USBAUDIO_OT_MIC, 0, AUDIO_TERMTYPE_USB_STREAM, USBAUDIO_IT_MIC),
	//	USB_ACS_ACI_OT(USBAUDIO_OT_SPK, 0, AUDIO_TERMTYPE_OT_SPK, USBAUDIO_IT_SPK),
	// MIC desc
	USB_AUDIO_IntfAltAS_BW0(USB_INTFID_AudioAS_MIC, 0),
	USB_AUDIO_InterfaceAS(USB_INTFID_AudioAS_MIC, 1),
	USB_ACS_ASI_General(USBAUDIO_OT_MIC, 1, 0x0001),
	USB_ACS_ASI_FmtTypeI(AUDIO_MIC_CHNs, AUDIO_MIC_BR, 1), Byte3Data(AUDIO_MIC_SAMPRATE),
	USB_AUDIO_EndpAS_IN(USB_ENDPID_Audio_MIC, 0 /*AUDIO_SYNCMODE_SYNC*/, AUDIO_MAXP(AUDIO_MIC_CHNs, AUDIO_MIC_BR, AUDIO_MIC_SAMPRATE)),
	USB_ACS_EP_General(0),
	// SPK desc
	// USB_AUDIO_IntfAltAS_BW0(USB_INTFID_AudioAS_SPK, 0),
	// USB_AUDIO_InterfaceAS(USB_INTFID_AudioAS_SPK, 1),
	// USB_ACS_ASI_General(USBAUDIO_IT_SPK, 1, 0x0001),
	// USB_ACS_ASI_FmtTypeI(AUDIO_SPK_CHNs, AUDIO_SPK_BR, 1), Byte3Data(AUDIO_SPK_SAMPRATE),
	// USB_AUDIO_EndpAS_OUT(USB_ENDPID_Audio_SPK, 0 /*AUDIO_SYNCMODE_SYNC*/, AUDIO_MAXP(AUDIO_SPK_CHNs, AUDIO_SPK_BR, AUDIO_SPK_SAMPRATE)),
	// USB_ACS_EP_General(0),

	USB_INTERFACE_DESC(USB_INTFID_Hid_Mse, 0, 1, USB_DEVICE_CLASS_HID, 0, 0),
	USB_HID_CLS_DESC(tHidMSEReportDesc),
	USB_HID_EndpIN(USB_ENDPID_Hid_MSE, 8, 1),
	USB_INTERFACE_DESC(USB_INTFID_Hid_Dbg, 0, 2, USB_DEVICE_CLASS_HID, 0, 0),
	USB_HID_CLS_DESC(tHidDbgReportDesc),
	USB_HID_EndpIN(USB_ENDPID_Hid_DBG_IN, 64, 1),
	USB_HID_EndpOUT(USB_ENDPID_Hid_DBG_OUT, 64, 1)};
#endif

const CBufferBaseDesc _c_device_desc = {(void *)&tUsbDeviceDescriptor, sizeof(tUsbDeviceDescriptor)};
const CBufferBaseDesc _c_config_desc = {(void *)tUsbConfig, sizeof(tUsbConfig)};
const _t_index_descriptor tblUsbHidRptDescs[] = {
	{USB_INTFID_Hid_Mse, {(void *)tHidMSEReportDesc, sizeof(tHidMSEReportDesc)}},
	{USB_INTFID_Hid_Dbg, {(void *)tHidDbgReportDesc, sizeof(tHidDbgReportDesc)}},
};
const _t_index_descriptor tblUsbStringDescs[] = {
	{_Language_String_ID_, {(void *)tUsbLanguageID, sizeof(tUsbLanguageID)}},
	{_Vendor_String_ID_, {(void *)tUsbVendorStr, sizeof(tUsbVendorStr)}},
	{_Product_String_ID_, {(void *)tUsbProductStr, sizeof(tUsbProductStr)}},
	{_Sn_String_ID_, {(void *)tUsbSnStr, sizeof(tUsbSnStr)}},
};

void *USBDesc_GetDeviceDesc(void)
{
	return (void *)&_c_device_desc;
}

void *USBDesc_GetConfigDesc(void)
{
	return (void *)&_c_config_desc;
}
void *UsbDesc_Find(int idx, void *tb, int cnt)
{
	_t_index_descriptor *ptbl = (_t_index_descriptor *)tb;
	int i;
	for (i = 0; i < cnt; i++)
	{
		if (ptbl[i].ind == idx)
		{
			return (void *)&ptbl[i].desc;
		}
	}
	return (NULL);
}

void *USBDesc_GetHidRptDesc(int idx)
{
	return UsbDesc_Find(idx, (void *)tblUsbHidRptDescs, GET_ELEMENT_TBL(tblUsbHidRptDescs));
}

void *USBDesc_GetStringDesc(int idx)
{
	return UsbDesc_Find(idx, (void *)tblUsbStringDescs, GET_ELEMENT_TBL(tblUsbStringDescs));
}
